package org.idea.spring.framework.tx.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.idea.spring.framework.tx.config.MyTransaction;
import org.idea.spring.framework.tx.config.TransactionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.web.servlet.DispatcherServlet;

import java.lang.reflect.Method;

/**
 * @Author linhao
 * @Date created in 6:46 下午 2021/5/21
 */
@Aspect
@Component
public class TransactionAop {

    @Autowired
    private TransactionUtils transactionUtils;

    @AfterThrowing("execution(* org.idea.spring.framework.tx.*.*(..))")
    public void afterThrowing(){
        transactionUtils.rollback();
    }

    // 环绕通知 在方法之前和之后处理事情
    @Around("execution(* org.idea.spring.framework.tx.*.*(..))")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        MyTransaction extTransaction = getMethodExtTransaction(pjp);
        TransactionStatus transactionStatus = null;
        if(extTransaction!=null) {
            transactionStatus = transactionUtils.begin();
        }
        pjp.proceed();
        if(transactionStatus!=null){
            transactionUtils.commit(transactionStatus);
        }
        DispatcherServlet dispatcherServlet;
        Resource resource;
    }

    public MyTransaction getMethodExtTransaction(ProceedingJoinPoint pjp) throws NoSuchMethodException {
        String methodName = pjp.getSignature().getName();
        // 获取目标对象
        Class<?> classTarget = pjp.getTarget().getClass();
        // 获取目标对象类型
        Class<?>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
        Method method = classTarget.getMethod(methodName,par);
        return method.getDeclaredAnnotation(MyTransaction.class);
    }
}
